package cn.tradewin.advisor.activiti.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;

import cn.tradewin.advisor.activiti.service.ActivitiProcessStatus;
import cn.tradewin.advisor.activiti.service.ActivitiService;

public class ActivitiServiceImpl implements ActivitiService {

	private static Map<String, ProcessDefinition> PROCESS_DEFINITION_CACHE = new HashMap<String, ProcessDefinition>();

	private final RepositoryService repositoryService;

	private final RuntimeService runtimeService;

	private final TaskService taskService;

	private final HistoryService historyService;

	private final Logger log;

	public ActivitiServiceImpl(Logger log,
			RepositoryService repositoryService,
			RuntimeService runtimeService, TaskService taskService,
			HistoryService historyService) {
		this.log = log;
		this.repositoryService = repositoryService;
		this.runtimeService = runtimeService;
		this.taskService = taskService;
		this.historyService = historyService;
	}

	@Override
	public ProcessDefinition findProcessDefinitionByDefinitionId(
			String processDefinitionId) throws Exception {
		ProcessDefinition processDefinition = PROCESS_DEFINITION_CACHE
				.get(processDefinitionId);
		if (processDefinition == null) {
			processDefinition = repositoryService
					.createProcessDefinitionQuery()
					.processDefinitionId(processDefinitionId).singleResult();
			PROCESS_DEFINITION_CACHE
					.put(processDefinitionId, processDefinition);
		}
		return processDefinition;
	}

	@Override
	public ProcessDefinition findProcessDefinitionByProcessInstanceId(
			String processInstanceId) throws Exception {
		HistoricProcessInstance historicProcessInstance = historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		return findProcessDefinitionByDefinitionId(historicProcessInstance
				.getProcessDefinitionId());

	}

	@Override
	public List<Map<String, Object>> traceProcess(String processInstanceId)
			throws Exception {
		return null;
	}

	@Override
	public List<Map<String, Object>> todoList(String userid) throws Exception {

		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm");

		// 已经签收的任务
		List<Task> todoList = taskService.createTaskQuery()
				.taskAssignee(userid).active().list();
		for (Task task : todoList) {
			String processDefinitionId = task.getProcessDefinitionId();
			ProcessDefinition processDefinition = findProcessDefinitionByDefinitionId(processDefinitionId);
			Map<String, Object> singleTask = packageTaskInfo(sdf, task,
					processDefinition);
			singleTask.put("status", "todo");
			result.add(singleTask);
		}

		// 等待签收的任务
		List<Task> toClaimList = taskService.createTaskQuery()
				.taskCandidateUser(userid).active().list();
		for (Task task : toClaimList) {
			String processDefinitionId = task.getProcessDefinitionId();
			ProcessDefinition processDefinition = findProcessDefinitionByDefinitionId(processDefinitionId);
			Map<String, Object> singleTask = packageTaskInfo(sdf, task,
					processDefinition);
			singleTask.put("status", "claim");
			result.add(singleTask);
		}
		return result;
	}

	private Map<String, Object> packageTaskInfo(SimpleDateFormat sdf,
			Task task, ProcessDefinition processDefinition) {
		Map<String, Object> singleTask = new HashMap<String, Object>();
		singleTask.put("id", task.getId());
		singleTask.put("name", task.getName());
		singleTask.put("createTime", sdf.format(task.getCreateTime()));
		singleTask.put("pdname", processDefinition.getName());
		singleTask.put("pdversion", processDefinition.getVersion());
		singleTask.put("pid", task.getProcessInstanceId());
		return singleTask;
	}
	
	public ActivitiProcessStatus getProcessStatus(String processInstanceId) {
		ProcessInstance processInstance = runtimeService
				.createProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		if (processInstance == null) return ActivitiProcessStatus.ENDED;
		if (processInstance.isEnded()) return ActivitiProcessStatus.ENDED;
		if (processInstance.isSuspended()) return ActivitiProcessStatus.SUSPENDED;
		return ActivitiProcessStatus.ACTIVE;
	}
	
	
	@Override
	public String getCurrentActivitiName(String processInstanceId)
			throws Exception {
		Task task = this.getCurrentActivity(processInstanceId);
		if (task != null) {
			return task.getName();
		}
		return "";
	}
	
	@Override
	public Task getCurrentActivity(String processInstanceId)
			throws Exception {

		List<Task> tasks = taskService.createTaskQuery().executionId(processInstanceId).active().list();
		
		if (tasks.size() > 0) {
			return tasks.get(0);
		}
		return null;
		
		
		
		
//		ProcessInstance processInstance = runtimeService
//				.createProcessInstanceQuery()
//				.processInstanceId(processInstanceId).singleResult();
//		
//		if (processInstance.isEnded() || processInstance.isSuspended()) {
//			return null;
//		}
//		
//		String activityId = processInstance.getActivityId();
//		
//		repositoryService.getProcessDefinition(processInstanceId).getId();
//		
//		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService
//				.getDeployedProcessDefinition(processInstance
//						.getProcessDefinitionId());
//		// 获得当前流程的所有节点
//		List<ActivityImpl> activitiList = processDefinitionEntity
//				.getActivities();
//
//		for (ActivityImpl activity : activitiList) {
//			String id = activity.getId();
//			// 当前节点
//			if (id.equals(activityId)) {
//				return activity;
//			}
//		}
//		return null;
	}
}
